/*
 * Copyright (C) 2010 The Android Open Source Project 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */

/*
 * Sources:
 *  http://developer.android.com/guide/topics/ui/ui-events.html
 *  http://developer.android.com/reference/android/view/MotionEvent.html
 */

package com.gameoflife;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/** 
 * Displays the state of the game and allows user to touch to add new cells. 
 */
public class GridView extends View {
    
	/** Constants for game state */
    public static final int PAUSE = 0;
    public static final int RUNNING = 1;
    
    /** Game model that handles updating from generation to generation. */
    private Life _life;
    
    private RefreshHandler _redrawHandler = new RefreshHandler();

    class RefreshHandler extends Handler {

        @Override
        public void handleMessage(Message message) {
            GridView.this.update();
            GridView.this.invalidate();
        }

        public void sleep(long delayMillis) {
            this.removeMessages(0);
            sendMessageDelayed(obtainMessage(0), delayMillis);
        }
    };

    /** Constructor for GridView - sets up the game logic and initializes the view. */
    public GridView(Context context, AttributeSet attrs) {
        super(context, attrs);
        _life = new Life(context);
        initGridView();
    }
    
    /** Change the state of the game between running and paused. */
    public void setMode(int mode) {
        if (mode == RUNNING) {
            update();
            return;
        }
        if (mode == PAUSE) {
        	// This was never implemented in the tutorial nor was a requirement of the project
            // TODO: implement.
        }
    }
    
    /** 
     * Gets the grid of cells from Life and draws them. If color mode is on, color the cells
     *  appropriately. 
     */
    @Override
    protected void onDraw(Canvas canvas) {
        Paint background = new Paint();
        background.setColor(getResources().getColor(R.color.background));

        Paint cell = new Paint();
        cell.setColor(getResources().getColor(R.color.cell));

        // draw background
        canvas.drawRect(0, 0, getWidth(), getHeight(), background);

        // draw cells
        for (int h = 0; h < _life.height; h++) {
            for (int w = 0; w < _life.width; w++) {
                if (_life.getGrid()[h][w] != 0) {
                	if(PreferencesActivity.getColorCoding(getContext())){
                    	cell.setColor(setCellColor(_life.getColorGrid()[h][w]));
                    }
                    canvas.drawRect(
                        w * _life.cellSize, 
                        h * _life.cellSize, 
                        (w * _life.cellSize) + (_life.cellSize -1),
                        (h * _life.cellSize) + (_life.cellSize -1),
                        cell);
                }
            }
        }
    }
    
    /** Capture touch events and send them to the model. */
	@Override
    public boolean onTouchEvent(MotionEvent event){
    	switch(event.getAction()){
	    	case MotionEvent.ACTION_DOWN:
	    		_life.touchCell(event.getX(), event.getY());
	    		break;
    		// For move events, touch all the cells that are in the pointer batch
	    	case MotionEvent.ACTION_MOVE:
	    		for (int i = 0; i < event.getHistorySize(); i++){
	    			_life.touchCell(event.getHistoricalX(i), event.getHistoricalY(i));
	    		}
	    		break;
	    	case MotionEvent.ACTION_UP:
	    		_life.touchCell(event.getX(), event.getY());
	    		break;
    	}
    	return true;
    }
    
	/** Get the new state of the board and wait to draw new frame. */
    private void update() {
        _life.generateNextGeneration();
        _redrawHandler.sleep(getMoveDelay());
    }
    
    private void initGridView() {
        setFocusable(true);
    }
    
    /** Get the color of a cell based on how long it has been alive. */
    private int setCellColor(int state){
    	int color;
    	if (state < 1){
    		color = getResources().getColor(R.color.cellBaby);
    	}
    	else if (state >= 1 && state < 3){
    		color = getResources().getColor(R.color.cellYoung);
    	}
    	else if(state >= 3 && state < 5){
    		color = getResources().getColor(R.color.cellMiddleAge);
    	}
    	else if (state >= 5 && state < 8){
    		color = getResources().getColor(R.color.cellOld);
    	}
    	else{
    		color = getResources().getColor(R.color.cell);
    	}
    	return color;
    }
    
    /** Get the move delay selected in the settings. */
    private long getMoveDelay(){
    	long moveDelay;
    	switch(Integer.parseInt(PreferencesActivity.getAnimationSpeed(getContext()))){
    	default:
    	case 1:
    		moveDelay = 50;
    		break;
    	case 2:
    		moveDelay = 125;
    		break;
    	case 3:
    		moveDelay = 250;
    		break;
    	case 4:
    		moveDelay = 375;
    		break;
    	case 5:
    		moveDelay = 500;
    		break;
    	}
    	return moveDelay;
    }
}